﻿#include <openvino/openvino.hpp>
#include <iostream>
#include <windows.h>
#include <vector>
#include <stdlib.h>
#include <stdio.h>

class OpenVINODiagnostic {
public:
    void diagnose() {
        std::cout << "=== OpenVINO插件诊断 ===" << std::endl;

        // 1. 检查环境变量
        check_environment();

        // 2. 检查DLL文件
        check_dll_files();

        // 3. 检查插件注册
        check_plugin_registration();

        // 4. 尝试手动解决方案
        try_fix_solutions();
    }

private:
    void check_environment() {
        std::cout << "\n1. 检查环境变量..." << std::endl;

        char* path = nullptr;
        size_t len = 0;
        _dupenv_s(&path, &len, "PATH");

        if (path) {
            std::string path_str(path);
            if (path_str.find("openvino") != std::string::npos) {
                std::cout << "✓ PATH中包含OpenVINO路径" << std::endl;
            }
            else {
                std::cout << "✗ PATH中未找到OpenVINO路径" << std::endl;
            }
            free(path);
        }
    }

    void check_dll_files() {
        std::cout << "\n2. 检查DLL文件..." << std::endl;

        std::string base_path = "C:\\Intel\\openvino_2025.3.0\\runtime\\bin\\intel64\\Release\\";
        std::vector<std::string> critical_dlls = {
            "openvino.dll",
            "openvino_c.dll",
            "openvino_intel_cpu_plugin.dll",  // 这是关键的CPU插件
            "tbb12.dll",                      // Intel TBB库
            "tbbmalloc.dll"
        };

        for (const auto& dll : critical_dlls) {
            std::string full_path = base_path + dll;
            if (GetFileAttributesA(full_path.c_str()) != INVALID_FILE_ATTRIBUTES) {
                std::cout << "✓ " << dll << " 存在" << std::endl;
            }
            else {
                std::cout << "✗ " << dll << " 缺失!" << std::endl;
            }
        }
    }

    void check_plugin_registration() {
        std::cout << "\n3. 检查插件注册..." << std::endl;

        try {
            ov::Core core;

            // 尝试获取可用设备
            auto devices = core.get_available_devices();
            std::cout << "注册的设备数量: " << devices.size() << std::endl;

            if (devices.empty()) {
                std::cout << "❌ 没有设备被注册!" << std::endl;

                // 检查插件目录
                std::string plugin_dir = "C:\\Intel\\openvino_2025.3.0\\runtime\\bin\\intel64\\Release";
                std::cout << "插件目录: " << plugin_dir << std::endl;

                // 检查插件DLL是否能被加载
                check_plugin_dll_loading();
            }

        }
        catch (const std::exception& e) {
            std::cout << "❌ 核心初始化失败: " << e.what() << std::endl;
        }
    }

    void check_plugin_dll_loading() {
        std::cout << "\n4. 检查插件DLL加载..." << std::endl;

        std::string base_path = "C:\\Intel\\openvino_2025.3.0\\runtime\\bin\\intel64\\Release\\";
        std::vector<std::string> plugin_dlls = {
            "openvino_intel_cpu_plugin.dll"
        };

        for (const auto& dll : plugin_dlls) {
            std::string full_path = base_path + dll;
            HMODULE hModule = LoadLibraryA(full_path.c_str());

            if (hModule) {
                std::cout << "✓ " << dll << " 可以加载" << std::endl;

                // 检查是否有初始化函数
                FARPROC init_func = GetProcAddress(hModule, "ov_plugin_create_core");
                if (init_func) {
                    std::cout << "  ✓ 找到初始化函数" << std::endl;
                }
                else {
                    std::cout << "  ✗ 未找到初始化函数" << std::endl;
                }

                FreeLibrary(hModule);
            }
            else {
                DWORD error = GetLastError();
                std::cout << "✗ " << dll << " 加载失败 (错误: " << error << ")" << std::endl;

                if (error == 126) {
                    std::cout << "  -> 依赖的DLL缺失" << std::endl;
                    check_dependencies(dll);
                }
            }
        }
    }

    void check_dependencies(const std::string& dll_name) {
        std::cout << "   检查 " << dll_name << " 的依赖..." << std::endl;

        // 常见依赖问题
        std::vector<std::string> common_deps = {
            "tbb12.dll",
            "tbbmalloc.dll",
            "omp.dll",
            "openvino.dll",
            "openvino_c.dll"
        };

        std::string base_path = "C:\\Intel\\openvino_2025.3.0\\runtime\\bin\\intel64\\Release\\";

        for (const auto& dep : common_deps) {
            std::string full_path = base_path + dep;
            if (GetFileAttributesA(full_path.c_str()) != INVALID_FILE_ATTRIBUTES) {
                std::cout << "    ✓ " << dep << " 存在" << std::endl;
            }
            else {
                std::cout << "    ✗ " << dep << " 缺失!" << std::endl;
            }
        }
    }

    void try_fix_solutions() {
        std::cout << "\n5. 尝试解决方案..." << std::endl;

        // 方案1: 设置当前目录
        std::cout << "方案1: 设置当前目录到插件路径..." << std::endl;
        SetCurrentDirectoryA("C:\\Intel\\openvino_2025.3.0\\runtime\\bin\\intel64\\Release");

        // 方案2: 手动预加载DLL
        std::cout << "方案2: 手动预加载DLL..." << std::endl;
        preload_required_dlls();

        // 方案3: 重新测试
        std::cout << "方案3: 重新测试..." << std::endl;
        retest_openvino();
    }

    void preload_required_dlls() {
        std::string base_path = "C:\\Intel\\openvino_2025.3.0\\runtime\\bin\\intel64\\Release\\";

        // 按依赖顺序加载
        std::vector<std::string> load_order = {
            "tbb12.dll",
            "tbbmalloc.dll",
            "openvino.dll",
            "openvino_c.dll",
            "openvino_intel_cpu_plugin.dll"
        };

        for (const auto& dll : load_order) {
            std::string full_path = base_path + dll;
            HMODULE hModule = LoadLibraryA(full_path.c_str());
            if (hModule) {
                std::cout << "  ✓ 预加载: " << dll << std::endl;
                // 不要FreeLibrary，保持加载状态
            }
            else {
                std::cout << "  ✗ 预加载失败: " << dll << " (错误: " << GetLastError() << ")" << std::endl;
            }
        }
    }

    void retest_openvino() {
        try {
            ov::Core core;
            auto devices = core.get_available_devices();

            std::cout << "重新测试结果: " << devices.size() << " 个设备" << std::endl;
            for (const auto& device : devices) {
                std::cout << "  ✅ " << device << std::endl;
            }

        }
        catch (const std::exception& e) {
            std::cout << "重新测试失败: " << e.what() << std::endl;
        }
    }
};

/*
int main() {
    OpenVINODiagnostic diagnostic;
    diagnostic.diagnose();
    return 0;
}
*/